
/* Generated by Interface Builder */
/* This is certainly a grody file.  But it works.  So there.  I have a better one
 * around, which is Interface Builder custom palette compatible.  Give me time. */

#import "BounceView.h"
#import <appkit/Window.h>
#import <appkit/Application.h>
#import <dpsclient/wraps.h>
#import "Animator.h"
#import <appkit/publicWraps.h>
#import <strings.h>
#import <appkit/Bitmap.h>

@implementation BounceView

#define RANDINT( n) ((random() % (n+1))+1)

extern srandom(int);
extern long random();
extern long time( long *);

+ newFrame:(NXRect *)r
{
  int i;
  self = [super newFrame:r];
  [[NXApp appIcon] setContentView:self];
  for( i=0; i<4; i++)			// get random velocities.
    vel[ i]=(RANDINT( 1) ? 1 : -1)*(1+minVel+RANDINT( (maxVel-minVel)/2));
  pos[ 0][ 0]=pos[ 0][ 2]=bounds.size.width/2;
  pos[ 0][ 1]=pos[ 0][ 3]=bounds.size.height/2;
  for( i=0; i<numEdges; i++)
    [self moveLine];
  srandom( time( 0));
  return self;
}

- free
{
  [animator stop:self];
  [animator setTarget:nil];
  return [super free];
}

- setAnimator:anObject
{
  if( animator==anObject)			// nip loops in the bud.
    return self;
  animator=anObject;
  [animator setTarget:self];
  [animator setTiming:0.3];
  [animator setThreshold:NX_MODALRESPTHRESHOLD];	// this makes it run smoother. why?
  return self;
}

- animate:sender
{
  [self lockFocus];
  PSsetgray( NX_DKGRAY);
  PSnewpath();
  PSmoveto( bounds.origin.x+pos[ numEdges-1][ 0], bounds.origin.y+pos[ numEdges-1][ 1]);
  PSlineto( bounds.origin.x+pos[ numEdges-1][ 2], bounds.origin.y+pos[ numEdges-1][ 3]);
  PSstroke();
  [self moveLine];
  PSsetgray( NX_BLACK);
  PSnewpath();
  PSmoveto( bounds.origin.x+pos[ 0][ 0], bounds.origin.y+pos[ 0][ 1]);
  PSlineto( bounds.origin.x+pos[ 0][ 2], bounds.origin.y+pos[ 0][ 3]);
  PSstroke();
  [self unlockFocus];
  [[self window] flushWindow];
  NXPing();				// This makes it run smoother - else code is output
  					// in larger chunks.
  return self;
}

- animator
{
  return animator;
}

- drawSelf:(NXRect *)r :(int)count
{
  int i;
  PSsetgray( NX_DKGRAY);
  NXRectFill( &bounds);
  PSsetgray( NX_BLACK);
  PSnewpath();
  for( i=0; i<numEdges; i++)		// Not bad.  Could be a userpath, though.
    {
      PSmoveto( bounds.origin.x+pos[ i][ 0], bounds.origin.y+pos[ i][ 1]);
      PSlineto( bounds.origin.x+pos[ i][ 2], bounds.origin.y+pos[ i][ 3]);
    }
  PSstroke();
  [[self window] flushWindow];
  NXPing();				// Do we need to be smooth here?  Maybe not.
  					// but who cares, as we only redraw seldom.
  return self;
}

- moveLine			// This is stupid.  Anyone have a better way?  I once did,
				// but it was non-intuitive.  There must be some generic
				// method.  If so, please tell me.
{
    int i;
    bcopy( pos, &pos[ 1], sizeof( short)*4*(numEdges-1));
    for( i=0; i<4; i++)
      pos[ 0][ i]+=vel[ i];
    if( pos[ 0][ 0]>bounds.size.width || pos[ 0][ 0]<0)
      {
        if( pos[ 0][ 0]<0)
	  pos[ 0][ 0]=0;
	else
	  pos[ 0][ 0]=bounds.size.width-1;
	vel[ 0]=(vel[ 0]<0 ? 1 : -1)*(minVel+RANDINT( maxVel-minVel));
      }
    if( pos[ 0][ 1]>bounds.size.height || pos[ 0][ 1]<0)
      {
        if( pos[ 0][ 1]<0)
	  pos[ 0][ 1]=0;
	else
	  pos[ 0][ 1]=bounds.size.height-1;
	vel[ 1]=(vel[ 1]<0 ? 1 : -1)*(minVel+RANDINT( maxVel-minVel));
      }
    if( pos[ 0][ 2]>bounds.size.width || pos[ 0][ 2]<0)
      {
        if( pos[ 0][ 2]<0)
	  pos[ 0][ 2]=0;
	else
	  pos[ 0][ 2]=bounds.size.width-1;
	vel[ 2]=(vel[ 2]<0 ? 1 : -1)*(minVel+RANDINT( maxVel-minVel));
      }
    if( pos[ 0][ 3]>bounds.size.height || pos[ 0][ 3]<0)
      {
        if( pos[ 0][ 3]<0)
	  pos[ 0][ 3]=0;
	else
	  pos[ 0][ 3]=bounds.size.height-1;
	vel[ 3]=(vel[ 3]<0 ? 1 : -1)*(minVel+RANDINT( maxVel-minVel));
      }
    return self;
}

@end
